<!DOCTYPE html>
<html class="client-nojs vector-feature-night-mode-disabled vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-sticky-header-enabled" lang="en" dir="ltr"><head>
<meta charset="UTF-8">
<title>Dynamic perfect hashing</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="https://en.wikipedia.org/wiki/Dynamic_perfect_hashing"> <link href="./mw/ext.cite.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/ext.math.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/user.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link rel="stylesheet" type="text/css" href="./mw/site.styles.css">
<link rel="stylesheet" type="text/css" href="./mw/noscript.css">
<link rel="stylesheet" type="text/css" href="./footer.css">
<link rel="stylesheet" type="text/css" href="./vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-Dynamic_perfect_hashing rootpage-Dynamic_perfect_hashing skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading">
<span id="openzim-page-title" class="mw-page-title-main"><span class="mw-page-title-main">Dynamic perfect hashing</span></span>
</h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="en" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="en" dir="ltr">
<p>In <a href="Computer_science" title="Computer science">computer science</a>, <b>dynamic perfect hashing</b> is a programming technique for resolving <a href="Hash_collision" title="Hash collision">collisions</a> in a <a href="Hash_table" title="Hash table">hash table</a> <a href="Data_structure" title="Data structure">data structure</a>.<sup id="cite_ref-inventor_1-0" class="reference"><a href="#cite_note-inventor-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup><sup id="cite_ref-dietzfelbinger_2-0" class="reference"><a href="#cite_note-dietzfelbinger-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup><sup id="cite_ref-3" class="reference"><a href="#cite_note-3"><span class="cite-bracket">[</span>3<span class="cite-bracket">]</span></a></sup>
While more memory-intensive than its hash table counterparts, this technique is useful for situations where fast queries, insertions, and deletions must be made on a large set of elements.
</p>
<meta property="mw:PageProp/toc">
<div class="mw-heading mw-heading2"><h2 id="Details">Details</h2></div>
<div class="mw-heading mw-heading3"><h3 id="Static_case">Static case</h3></div>
<div class="mw-heading mw-heading4"><h4 id="FKS_Scheme">FKS Scheme</h4></div>
<style data-mw-deduplicate="TemplateStyles:r1236090951">
/* start https://en.wikipedia.org/ */
.mw-parser-output .hatnote{font-style:italic}.mw-parser-output div.hatnote{padding-left:1.6em;margin-bottom:0.5em}.mw-parser-output .hatnote i{font-style:normal}.mw-parser-output .hatnote+link+.hatnote{margin-top:-0.5em}@media print{body.ns-0 .mw-parser-output .hatnote{display:none!important}}
/* end https://en.wikipedia.org/ */
</style><div role="note" class="hatnote navigation-not-searchable">Main article: <a href="Static_hashing#FKS_Hashing" title="Static hashing">static hashing § FKS Hashing</a></div>
<p>The problem of optimal <a href="Static_hashing" title="Static hashing">static hashing</a> was first solved in general by Fredman, Komlós and Szemerédi.<sup id="cite_ref-4" class="reference"><a href="#cite_note-4"><span class="cite-bracket">[</span>4<span class="cite-bracket">]</span></a></sup> In their 1984 paper,<sup id="cite_ref-inventor_1-1" class="reference"><a href="#cite_note-inventor-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup> they detail a two-tiered hash table scheme in which each bucket of the (first-level) hash table corresponds to a separate second-level hash table. Keys are hashed twice—the first hash value maps to a certain bucket in the first-level hash table; the second hash value gives the position of that entry in that bucket's second-level hash table. The second-level table is guaranteed to be collision-free (i.e. <a href="Perfect_hashing" class="mw-redirect" title="Perfect hashing">perfect hashing</a>) upon construction. Consequently, the look-up cost is guaranteed to be <a href="Big_O_notation" title="Big O notation">O(1)</a> <a href="Worst-case_complexity" title="Worst-case complexity">in the worst-case</a>.<sup id="cite_ref-dietzfelbinger_2-1" class="reference"><a href="#cite_note-dietzfelbinger-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup>
</p><p>In the static case, we are given a set with a total of <span class="texhtml mvar" style="font-style:italic;">x</span> entries, each one with a unique key, ahead of time.
Fredman, Komlós and Szemerédi pick a first-level hash table with size <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle s=2(x-1)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>s</mi>
<mo>=</mo>
<mn>2</mn>
<mo stretchy="false">(</mo>
<mi>x</mi>
<mo>−<!-- − --></mo>
<mn>1</mn>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle s=2(x-1)}</annotation>
</semantics>
</math></span><img src="./00342f7424ef686e5b08d723b691ee57924c9ebc.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:12.493ex; height:2.843ex;" alt="{\displaystyle s=2(x-1)}" loading="lazy"></span> buckets.<sup id="cite_ref-dietzfelbinger_2-2" class="reference"><a href="#cite_note-dietzfelbinger-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup>
</p><p>To construct, <span class="texhtml mvar" style="font-style:italic;">x</span> entries are separated into <span class="texhtml mvar" style="font-style:italic;">s</span> buckets by the top-level hashing function, where <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle s=2(x-1)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>s</mi>
<mo>=</mo>
<mn>2</mn>
<mo stretchy="false">(</mo>
<mi>x</mi>
<mo>−<!-- − --></mo>
<mn>1</mn>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle s=2(x-1)}</annotation>
</semantics>
</math></span><img src="./00342f7424ef686e5b08d723b691ee57924c9ebc.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:12.493ex; height:2.843ex;" alt="{\displaystyle s=2(x-1)}" loading="lazy"></span>. Then for each bucket with <span class="texhtml mvar" style="font-style:italic;">k</span> entries, a second-level table is allocated with <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle k^{2}}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<msup>
<mi>k</mi>
<mrow class="MJX-TeXAtom-ORD">
<mn>2</mn>
</mrow>
</msup>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle k^{2}}</annotation>
</semantics>
</math></span><img src="./af6423cd00e3559de92c4bc497066ff1b12bbfc3.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:2.265ex; height:2.676ex;" alt="{\displaystyle k^{2}}" loading="lazy"></span> slots, and its <a href="Hash_function" title="Hash function">hash function</a> is selected at random from a <a href="Universal_hash_function" class="mw-redirect" title="Universal hash function">universal hash function</a> set so that it is collision-free (i.e. a <a href="Perfect_hash_function" title="Perfect hash function">perfect hash function</a>) and stored alongside the hash table. If the hash function randomly selected creates a table with collisions, a new hash function is randomly selected until a collision-free table can be guaranteed. Finally, with the collision-free hash, the <span class="texhtml mvar" style="font-style:italic;">k</span> entries are hashed into the second-level table.
</p><p>The quadratic size of the <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle k^{2}}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<msup>
<mi>k</mi>
<mrow class="MJX-TeXAtom-ORD">
<mn>2</mn>
</mrow>
</msup>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle k^{2}}</annotation>
</semantics>
</math></span><img src="./af6423cd00e3559de92c4bc497066ff1b12bbfc3.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:2.265ex; height:2.676ex;" alt="{\displaystyle k^{2}}" loading="lazy"></span> space ensures that randomly creating a table with collisions is infrequent and independent of the size of <span class="texhtml mvar" style="font-style:italic;">k</span>, providing linear amortized construction time. Although each second-level table requires quadratic space, if the keys inserted into the first-level hash table are <a href="Uniform_distribution_(discrete)" class="mw-redirect" title="Uniform distribution (discrete)">uniformly distributed</a>, the structure as a whole occupies expected <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(n)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mi>n</mi>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(n)}</annotation>
</semantics>
</math></span><img src="./34109fe397fdcff370079185bfdb65826cb5565a.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.977ex; height:2.843ex;" alt="{\displaystyle O(n)}" loading="lazy"></span> space, since bucket sizes are small with high <a href="Probability" title="Probability">probability</a>.<sup id="cite_ref-inventor_1-2" class="reference"><a href="#cite_note-inventor-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup>
</p><p>The first-level hash function is specifically chosen so that, for the specific set of <span class="texhtml mvar" style="font-style:italic;">x</span> unique key values, the total space <span class="texhtml mvar" style="font-style:italic;">T</span> used by all the second-level hash tables has expected <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(n)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mi>n</mi>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(n)}</annotation>
</semantics>
</math></span><img src="./34109fe397fdcff370079185bfdb65826cb5565a.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.977ex; height:2.843ex;" alt="{\displaystyle O(n)}" loading="lazy"></span> space, and more specifically <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle T<s+4\cdot x}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>T</mi>
<mo><</mo>
<mi>s</mi>
<mo>+</mo>
<mn>4</mn>
<mo>⋅<!-- ⋅ --></mo>
<mi>x</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle T<s+4\cdot x}</annotation>
</semantics>
</math></span><img src="./77d4a841eb4f5c895bba0ec2863ef0d62e5ccabb.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.505ex; width:12.837ex; height:2.343ex;" alt="{\displaystyle T<s+4\cdot x}" loading="lazy"></span>.
Fredman, Komlós and Szemerédi showed that given a <a href="Universal_hashing" title="Universal hashing">universal hashing</a> family of hash functions, at least half of those functions have that property.<sup id="cite_ref-dietzfelbinger_2-3" class="reference"><a href="#cite_note-dietzfelbinger-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading3"><h3 id="Dynamic_case">Dynamic case</h3></div>
<p>Dietzfelbinger et al. present a dynamic dictionary algorithm that, when a set of n items is incrementally added to the dictionary, membership queries always run in constant time and therefore <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(1)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mn>1</mn>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(1)}</annotation>
</semantics>
</math></span><img src="./e66384bc40452c5452f33563fe0e27e803b0cc21.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.745ex; height:2.843ex;" alt="{\displaystyle O(1)}" loading="lazy"></span> worst-case time, the total storage required is <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(n)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mi>n</mi>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(n)}</annotation>
</semantics>
</math></span><img src="./34109fe397fdcff370079185bfdb65826cb5565a.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.977ex; height:2.843ex;" alt="{\displaystyle O(n)}" loading="lazy"></span> (linear), and <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(1)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mn>1</mn>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(1)}</annotation>
</semantics>
</math></span><img src="./e66384bc40452c5452f33563fe0e27e803b0cc21.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.745ex; height:2.843ex;" alt="{\displaystyle O(1)}" loading="lazy"></span> expected amortized insertion and deletion time (<a href="Amortized_constant_time" class="mw-redirect" title="Amortized constant time">amortized constant time</a>).
</p><p>In the dynamic case, when a key is inserted into the hash table, if its entry in its respective subtable is occupied, then a collision is said to occur and the subtable is rebuilt based on its new total entry count and randomly selected hash function. Because the <a href="Hash_table#Load_factor" title="Hash table">load factor</a> of the second-level table is kept low <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle 1/k}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mn>1</mn>
<mrow class="MJX-TeXAtom-ORD">
<mo>/</mo>
</mrow>
<mi>k</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle 1/k}</annotation>
</semantics>
</math></span><img src="./a7e9fedad8c70c6331b2640b56c23cef8c884e1f.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:3.536ex; height:2.843ex;" alt="{\displaystyle 1/k}" loading="lazy"></span>, rebuilding is infrequent, and the <a href="Amortized_analysis" title="Amortized analysis">amortized</a> expected cost of insertions is <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(1)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mn>1</mn>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(1)}</annotation>
</semantics>
</math></span><img src="./e66384bc40452c5452f33563fe0e27e803b0cc21.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.745ex; height:2.843ex;" alt="{\displaystyle O(1)}" loading="lazy"></span>.<sup id="cite_ref-dietzfelbinger_2-4" class="reference"><a href="#cite_note-dietzfelbinger-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup> Similarly, the amortized expected cost of deletions is <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(1)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mn>1</mn>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(1)}</annotation>
</semantics>
</math></span><img src="./e66384bc40452c5452f33563fe0e27e803b0cc21.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.745ex; height:2.843ex;" alt="{\displaystyle O(1)}" loading="lazy"></span>.<sup id="cite_ref-dietzfelbinger_2-5" class="reference"><a href="#cite_note-dietzfelbinger-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup>
</p><p>Additionally, the ultimate sizes of the top-level table or any of the subtables is unknowable in the dynamic case. One method for maintaining expected <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(n)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mi>n</mi>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(n)}</annotation>
</semantics>
</math></span><img src="./34109fe397fdcff370079185bfdb65826cb5565a.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.977ex; height:2.843ex;" alt="{\displaystyle O(n)}" loading="lazy"></span> space of the table is to prompt a full reconstruction when a sufficient number of insertions and deletions have occurred. By results due to Dietzfelbinger et al.,<sup id="cite_ref-dietzfelbinger_2-6" class="reference"><a href="#cite_note-dietzfelbinger-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup> as long as the total number of insertions or deletions exceeds the number of elements at the time of last construction, the amortized expected cost of insertion and deletion remain <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(1)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mn>1</mn>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(1)}</annotation>
</semantics>
</math></span><img src="./e66384bc40452c5452f33563fe0e27e803b0cc21.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.745ex; height:2.843ex;" alt="{\displaystyle O(1)}" loading="lazy"></span> with full rehashing taken into consideration.
</p><p>The implementation of dynamic perfect hashing by Dietzfelbinger et al. uses these concepts, as well as <a href="Lazy_deletion" title="Lazy deletion">lazy deletion</a>, and is shown in pseudocode below.
</p>
<div class="mw-heading mw-heading2"><h2 id="Pseudocode_implementation">Pseudocode implementation</h2></div>
<div class="mw-heading mw-heading3"><h3 id="Locate">Locate</h3></div>
<pre><b>function</b> Locate(<i>x</i>) <b>is</b>
<i>j</i> := h(<b>x</b>)
<b>if</b> (position h<sub>j</sub>(<i>x</i>) of subtable <i>T<sub>j</sub></i> contains <i>x</i> (not deleted))
<b>return</b> (<i>x</i> is in <i>S</i>)
<b>end if</b>
<b>else</b>
<b>return</b> (<i>x</i> is not in <i>S</i>)
<b>end else</b>
<b>end</b>
</pre>
<div class="mw-heading mw-heading3"><h3 id="Insert">Insert</h3></div>
<p>During the insertion of a new entry <i>x</i> at <i>j</i>, the global operations counter, <i>count</i>, is incremented.
</p><p>If <i>x</i> exists at <i>j</i>, but is marked as deleted, then the mark is removed.
</p><p>If <i>x</i> exists at <i>j</i> or at the subtable <i>T<sub>j</sub></i>, and is not marked as deleted, then a collision is said to occur and the <i>j</i><sup>th</sup> bucket's second-level table <i>T<sub>j</sub></i> is rebuilt with a different randomly selected hash function <i>h<sub>j</sub></i>.
</p>
<pre><b>function</b> Insert(<i>x</i>) <b>is</b>
<i>count</i> = <i>count</i> + 1;
<b>if</b> (<i>count</i> > <i>M</i>)
FullRehash(<i>x</i>);
<b>end if</b>
<b>else</b>
<i>j</i> := h(<i>x</i>);
<b>if</b> (Position h<sub><i>j</i></sub>(x) of subtable <i>T<sub>j</sub></i> contains <i>x</i>)
<b>if</b> (<i>x</i> is marked deleted)
remove the delete marker;
<b>end if</b>
<b>end if</b>
<b>else</b>
<i>b<sub>j</sub></i> = <i>b<sub>j</sub></i> + 1;
<b>if</b> (<i>b<sub>j</sub></i> <= <i>m<sub>j</sub></i>)
<b>if</b> position h<sub><i>j</i></sub>(<i>x</i>) of <i>T<sub>j</sub></i> is empty
store <i>x</i> in position h<sub><i>j</i></sub>(<i>x</i>) of <i>T<sub>j</sub></i>;
<b>end if</b>
<b>else</b>
Put all unmarked elements of <i>T<sub>j</sub></i> in list <i>L<sub>j</sub></i>;
Append <i>x</i> to list <i>L<sub>j</sub></i>;
<i>b<sub>j</sub></i> = length of <i>L<sub>j</sub></i>;
<b>repeat</b>
<i>h<sub>j</sub></i> = randomly chosen function in <i>H<sub>sj</sub></i>;
<b>until</b> <i>h<sub>j</sub></i> is injective on the elements of <i>L<sub>j</sub></i>;
<b>for</b> all <i>y</i> on list <i>L<sub>j</sub></i>
store <i>y</i> in position h<sub><i>j</i></sub>(<i>y</i>) of <i>T<sub>j</sub></i>;
<b>end for</b>
<b>end else</b>
<b>end if</b>
<b>else</b>
<i>m<sub>j</sub></i> = 2 * max{1, <i>m<sub>j</sub></i>};
<i>s<sub>j</sub></i> = 2 * <i>m<sub>j</sub></i> * (<i>m<sub>j</sub></i> - 1);
<b>if</b> the sum total of all s<sub>j</sub> ≤ 32 * <i>M</i><sup>2</sup> / <i>s</i>(<i>M</i>) + 4 * <i>M</i>
Allocate <i>s<sub>j</sub></i> cells for <i>T<sub>j</sub></i>;
Put all unmarked elements of <i>T<sub>j</sub></i> in list <i>L<sub>j</sub></i>;
Append <i>x</i> to list <i>L<sub>j</sub></i>;
<i>b<sub>j</sub></i> = length of <i>L<sub>j</sub></i>;
<b>repeat</b>
<i>h<sub>j</sub></i> = randomly chosen function in <i>H<sub>sj</sub></i>;
<b>until</b> <i>h<sub>j</sub></i> is injective on the elements of <i>L<sub>j</sub></i>;
<b>for</b> all <i>y</i> on list <i>L<sub>j</sub></i>
store <i>y</i> in position h<sub><i>j</i></sub>(<i>y</i>) of <i>T<sub>j</sub></i>;
<b>end for</b>
<b>end if</b>
<b>else</b>
FullRehash(<i>x</i>);
<b>end else</b>
<b>end else</b>
<b>end else</b>
<b>end else</b>
<b>end</b>
</pre>
<div class="mw-heading mw-heading3"><h3 id="Delete">Delete</h3></div>
<p>Deletion of <i>x</i> simply flags <i>x</i> as deleted without removal and increments <i>count</i>. In the case of both insertions and deletions, if <i>count</i> reaches a threshold <i>M</i> the entire table is rebuilt, where <i>M</i> is some constant multiple of the size of S at the start of a new <i>phase</i>. Here <i>phase</i> refers to the time between full rebuilds. Note that here the -1 in "Delete(<i>x</i>)" is a representation of an element which is not in the set of all possible elements <i>U</i>.
</p>
<pre><b>function</b> Delete(<i>x</i>) <b>is</b>
<i>count</i> = <i>count</i> + 1;
<i>j</i> = h(<i>x</i>);
<b>if</b> position h<sub>j</sub>(<i>x</i>) of subtable <i>Tj</i> contains <i>x</i>
mark <i>x</i> as deleted;
<b>end if</b>
<b>else</b>
<b>return</b> (x is not a member of S);
<b>end else</b>
<b>if</b> (<i>count</i> >= <i>M</i>)
FullRehash(-1);
<b>end if</b>
<b>end</b>
</pre>
<div class="mw-heading mw-heading3"><h3 id="Full_rebuild">Full rebuild</h3></div>
<p>A full rebuild of the table of <i>S</i> first starts by removing all elements marked as deleted and then setting the next threshold value <i>M</i> to some constant multiple of the size of <i>S</i>. A hash function, which partitions <i>S</i> into <i>s</i>(<i>M</i>) subsets, where the size of subset <i>j</i> is <i>s<sub>j</sub></i>, is repeatedly randomly chosen until:
</p><p><span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle \sum _{0\leq j\leq s(M)}s_{j}\leq {\frac {32M^{2}}{s(M)}}+4M.}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<munder>
<mo>∑<!-- ∑ --></mo>
<mrow class="MJX-TeXAtom-ORD">
<mn>0</mn>
<mo>≤<!-- ≤ --></mo>
<mi>j</mi>
<mo>≤<!-- ≤ --></mo>
<mi>s</mi>
<mo stretchy="false">(</mo>
<mi>M</mi>
<mo stretchy="false">)</mo>
</mrow>
</munder>
<msub>
<mi>s</mi>
<mrow class="MJX-TeXAtom-ORD">
<mi>j</mi>
</mrow>
</msub>
<mo>≤<!-- ≤ --></mo>
<mrow class="MJX-TeXAtom-ORD">
<mfrac>
<mrow>
<mn>32</mn>
<msup>
<mi>M</mi>
<mrow class="MJX-TeXAtom-ORD">
<mn>2</mn>
</mrow>
</msup>
</mrow>
<mrow>
<mi>s</mi>
<mo stretchy="false">(</mo>
<mi>M</mi>
<mo stretchy="false">)</mo>
</mrow>
</mfrac>
</mrow>
<mo>+</mo>
<mn>4</mn>
<mi>M</mi>
<mo>.</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle \sum _{0\leq j\leq s(M)}s_{j}\leq {\frac {32M^{2}}{s(M)}}+4M.}</annotation>
</semantics>
</math></span><img src="./235d1cc5a19ca0dd4616718435917916e9b8431f.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -3.505ex; width:27.126ex; height:7.343ex;" alt="{\displaystyle \sum _{0\leq j\leq s(M)}s_{j}\leq {\frac {32M^{2}}{s(M)}}+4M.}" loading="lazy"></span>
</p><p>Finally, for each subtable <i>T<sub>j</sub></i> a hash function <i>h<sub>j</sub></i> is repeatedly randomly chosen from <i>H<sub>sj</sub></i> until <i>h<sub>j</sub></i> is injective on the elements of <i>T<sub>j</sub></i>. The expected time for a full rebuild of the table of <i>S</i> with size <i>n</i> is O(<i>n</i>).<sup id="cite_ref-dietzfelbinger_2-7" class="reference"><a href="#cite_note-dietzfelbinger-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup>
</p>
<pre><b>function</b> FullRehash(<i>x</i>) <b>is</b>
Put all unmarked elements of <i>T</i> in list <i>L</i>;
<b>if</b> (<i>x</i> is in <i>U</i>)
append <i>x</i> to <i>L</i>;
<b>end if</b>
<i>count</i> = length of list <i>L</i>;
<i>M</i> = (1 + <i>c</i>) * max{<i>count</i>, 4};
<b>repeat</b>
h = randomly chosen function in <i>H<sub>s(M)</sub></i>;
<b>for</b> all <i>j</i> < <i>s</i>(<i>M</i>)
form a list <i>L<sub>j</sub></i> for h(<i>x</i>) = <i>j</i>;
<i>b<sub>j</sub></i> = length of <i>L<sub>j</sub></i>;
<i>m<sub>j</sub></i> = 2 * <i>b<sub>j</sub></i>;
<i>s<sub>j</sub></i> = 2 * <i>m<sub>j</sub></i> * (<i>m<sub>j</sub></i> - 1);
<b>end for</b>
<b>until</b> the sum total of all s<sub>j</sub> ≤ 32 * <i>M</i><sup>2</sup> / <i>s</i>(<i>M</i>) + 4 * <i>M</i>
<b>for</b> all <i>j</i> < <i>s</i>(<i>M</i>)
Allocate space <i>s<sub>j</sub></i> for subtable <i>T<sub>j</sub></i>;
<b>repeat</b>
<i>h<sub>j</sub></i> = randomly chosen function in <i>H<sub>sj</sub></i>;
<b>until</b> <i>h<sub>j</sub></i> is injective on the elements of list <i>L<sub>j</sub></i>;
<b>end for</b>
<b>for</b> all <i>x</i> on list <i>L<sub>j</sub></i>
store <i>x</i> in position h<sub><i>j</i></sub>(<i>x</i>) of <i>T<sub>j</sub></i>;
<b>end for</b>
<b>end</b>
</pre>
<div class="mw-heading mw-heading2"><h2 id="See_also">See also</h2></div>
<ul><li><a href="Perfect_hashing" class="mw-redirect" title="Perfect hashing">Perfect hashing</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="References">References</h2></div>
<style data-mw-deduplicate="TemplateStyles:r1239543626">
/* start https://en.wikipedia.org/ */
.mw-parser-output .reflist{margin-bottom:0.5em;list-style-type:decimal}@media screen{.mw-parser-output .reflist{font-size:90%}}.mw-parser-output .reflist .references{font-size:100%;margin-bottom:0;list-style-type:inherit}.mw-parser-output .reflist-columns-2{column-width:30em}.mw-parser-output .reflist-columns-3{column-width:25em}.mw-parser-output .reflist-columns{margin-top:0.3em}.mw-parser-output .reflist-columns ol{margin-top:0}.mw-parser-output .reflist-columns li{page-break-inside:avoid;break-inside:avoid-column}.mw-parser-output .reflist-upper-alpha{list-style-type:upper-alpha}.mw-parser-output .reflist-upper-roman{list-style-type:upper-roman}.mw-parser-output .reflist-lower-alpha{list-style-type:lower-alpha}.mw-parser-output .reflist-lower-greek{list-style-type:lower-greek}.mw-parser-output .reflist-lower-roman{list-style-type:lower-roman}
/* end https://en.wikipedia.org/ */
</style><div class="reflist">
<div class="mw-references-wrap"><ol class="references">
<li id="cite_note-inventor-1"><span class="mw-cite-backlink">^ <a href="#cite_ref-inventor_1-0"><sup><i><b>a</b></i></sup></a> <a href="#cite_ref-inventor_1-1"><sup><i><b>b</b></i></sup></a> <a href="#cite_ref-inventor_1-2"><sup><i><b>c</b></i></sup></a></span> <span class="reference-text">Fredman, M. L., Komlós, J., and Szemerédi, E. 1984. Storing a Sparse Table with 0(1) Worst Case Access Time. J. ACM 31, 3 (Jun. 1984), 538-544 <a rel="nofollow" class="external free" href="http://portal.acm.org/citation.cfm?id=1884#">http://portal.acm.org/citation.cfm?id=1884#</a></span>
</li>
<li id="cite_note-dietzfelbinger-2"><span class="mw-cite-backlink">^ <a href="#cite_ref-dietzfelbinger_2-0"><sup><i><b>a</b></i></sup></a> <a href="#cite_ref-dietzfelbinger_2-1"><sup><i><b>b</b></i></sup></a> <a href="#cite_ref-dietzfelbinger_2-2"><sup><i><b>c</b></i></sup></a> <a href="#cite_ref-dietzfelbinger_2-3"><sup><i><b>d</b></i></sup></a> <a href="#cite_ref-dietzfelbinger_2-4"><sup><i><b>e</b></i></sup></a> <a href="#cite_ref-dietzfelbinger_2-5"><sup><i><b>f</b></i></sup></a> <a href="#cite_ref-dietzfelbinger_2-6"><sup><i><b>g</b></i></sup></a> <a href="#cite_ref-dietzfelbinger_2-7"><sup><i><b>h</b></i></sup></a></span> <span class="reference-text">Dietzfelbinger, M., Karlin, A., Mehlhorn, K., Meyer auf der Heide, F., Rohnert, H., and Tarjan, R. E. 1994.
<a rel="nofollow" class="external text" href="http://www.arl.wustl.edu/~sailesh/download_files/Limited_Edition/hash/Dynamic%20Perfect%20Hashing-%20Upper%20and%20Lower%20Bounds.pdf">"Dynamic Perfect Hashing: Upper and Lower Bounds"</a> <a rel="nofollow" class="external text" href="https://web.archive.org/web/20160304094014/http://www.arl.wustl.edu/~sailesh/download_files/Limited_Edition/hash/Dynamic%20Perfect%20Hashing-%20Upper%20and%20Lower%20Bounds.pdf">Archived</a> 2016-03-04 at the <a href="Wayback_Machine" title="Wayback Machine">Wayback Machine</a>.
SIAM J. Comput. 23, 4 (Aug. 1994), 738-761.
<a rel="nofollow" class="external free" href="http://portal.acm.org/citation.cfm?id=182370">http://portal.acm.org/citation.cfm?id=182370</a>
<style data-mw-deduplicate="TemplateStyles:r1238218222">
/* start https://en.wikipedia.org/ */
.mw-parser-output cite.citation{font-style:inherit;word-wrap:break-word}.mw-parser-output .citation q{quotes:"\"""\"""'""'"}.mw-parser-output .citation:target{background-color:rgba(0,127,255,0.133)}.mw-parser-output .id-lock-free.id-lock-free a{background:url("./mw/Lock-green.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-limited.id-lock-limited a,.mw-parser-output .id-lock-registration.id-lock-registration a{background:url("./mw/Lock-gray-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-subscription.id-lock-subscription a{background:url("./mw/Lock-red-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .cs1-ws-icon a{background:url("./mw/Wikisource-logo.svg")right 0.1em center/12px no-repeat}body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-free a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-limited a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-registration a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-subscription a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .cs1-ws-icon a{background-size:contain;padding:0 1em 0 0}.mw-parser-output .cs1-code{color:inherit;background:inherit;border:none;padding:inherit}.mw-parser-output .cs1-hidden-error{display:none;color:var(--color-error,#d33)}.mw-parser-output .cs1-visible-error{color:var(--color-error,#d33)}.mw-parser-output .cs1-maint{display:none;color:#085;margin-left:0.3em}.mw-parser-output .cs1-kern-left{padding-left:0.2em}.mw-parser-output .cs1-kern-right{padding-right:0.2em}.mw-parser-output .citation .mw-selflink{font-weight:inherit}@media screen{.mw-parser-output .cs1-format{font-size:95%}html.skin-theme-clientpref-night .mw-parser-output .cs1-maint{color:#18911f}}@media screen and (prefers-color-scheme:dark){html.skin-theme-clientpref-os .mw-parser-output .cs1-maint{color:#18911f}}
/* end https://en.wikipedia.org/ */
</style><a href="Doi_(identifier)" class="mw-redirect" title="Doi (identifier)">doi</a>:<a rel="nofollow" class="external text" href="https://doi.org/10.1137%2FS0097539791194094">10.1137/S0097539791194094</a></span>
</li>
<li id="cite_note-3"><span class="mw-cite-backlink"><b><a href="#cite_ref-3">^</a></b></span> <span class="reference-text">
Erik Demaine, Jeff Lind.
<a rel="nofollow" class="external text" href="http://courses.csail.mit.edu/6.897/spring03/scribe_notes/L2/lecture2.pdf">6.897: Advanced Data Structures</a>.
MIT Computer Science and Artificial Intelligence Laboratory. Spring 2003.</span>
</li>
<li id="cite_note-4"><span class="mw-cite-backlink"><b><a href="#cite_ref-4">^</a></b></span> <span class="reference-text"><cite id="CITEREFYap" class="citation web cs1">Yap, Chee. <a rel="nofollow" class="external text" href="ftp://cs.nyu.edu/pub/local/yap/cg/hashFKS.ps.gz">"Universal Construction for the FKS Scheme"</a>. <i>New York University</i> (<a href="FTP" class="mw-redirect" title="FTP">FTP</a>)<span class="reference-accessdate">. Retrieved <span class="nowrap">15 February</span> 2015</span>.</cite> <span style="font-size:0.95em; font-size:95%; color: var( --color-subtle, #555 )">(To view documents see Help:FTP)</span></span>
</li>
</ol></div></div></div><!--htdig_noindex--><div><div class="zim-footer">
This article is issued from <a class="external text" title="Last edited on 2025-05-27" href="https://en.wikipedia.org/wiki/?title=Dynamic_perfect_hashing&oldid=1292513176">Wikipedia</a>. The text is available under <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">Creative Commons Attribution-Share Alike 4.0</a> unless otherwise noted. Additional terms may apply for the media files.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>
</body></html>